home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 Extra Demos / Maze Game / Scrolling Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-19  |  21.3 KB  |  763 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Scrolling Demo.c
  3. //
  4. // By Vern Jensen. Created in August of 1995
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWFPSReport.h>
  9. #include <SWIncludes.h>
  10. #include <SWGameUtils.h>
  11.  
  12. #include "SWApplication.h"
  13. #include "Scrolling Demo.h"
  14.  
  15.  
  16. #define kRequireDiamondsToExit        false        // If true, you must collect all diamonds to exit
  17.  
  18. #define    kFullScreenWindow            true        // Try me full screen!
  19. #define kWorldRectInset                0            // Make the SpriteWorld smaller?
  20. #define    kInterlacedMode                false        // Turns Interlaced mode on/off
  21. #define kSyncToVBL                    false        // Sync SpriteWorld to VBL?
  22. #define kMaxFPS                        20            // Set to 0 for unrestricted speed
  23.  
  24.  
  25. #define    kSpriteMoveDelta            20            // Try 5, 10, 20, or 40
  26. #define kDiamondSpace                8            // How far apart the diamonds are spaced
  27.                                                 // (try 1!)
  28.  
  29. #define kSpriteMoveDistance            80            // How far the sprite can move from
  30.                                                 // the center of the screen, in pixels.
  31.                                                 // Try making this value higher!
  32.  
  33.     // Number of ticks to wait before changing tile image; 0 = change every frame
  34. #define    kExitFrameRate                10
  35. #define kDiamondFrameRate            8            // How often diamond tiles change frames
  36. #define kWallFrameRate                120            // How often wall changes frames
  37.  
  38. #define kSpritePictResID            202
  39. #define kTilePictResID                200
  40. #define kTileWidth                    40
  41. #define kTileHeight                    40
  42.  
  43. #define kStartRow                    4            // Starting position of sprite
  44. #define kStartCol                    5            // in tile col and row
  45.  
  46.  
  47. #define    kLeftArrowKey                0x7B
  48. #define    kRightArrowKey                0x7C
  49. #define    kDownArrowKey                0x7D
  50. #define    kUpArrowKey                    0x7E
  51.  
  52. #define    kLeftKeyPad                    0x56
  53. #define    kRightKeyPad                0x58
  54. #define    kDownKeyPad                    0x54
  55. #define    kUpKeyPad                    0x5B
  56.  
  57. #define kEscKey                        0x35
  58.  
  59.  
  60. #define kNoKey                        0
  61. #define kLeftKey                    1
  62. #define kUpKey                        2
  63. #define kRightKey                    3
  64. #define kDownKey                    4
  65.  
  66.  
  67. enum tileIDs
  68. {
  69.     kFirstWallTile,
  70.     kLastWallTile = kFirstWallTile+13,
  71.     kFirstGrassTile,
  72.     kLastGrassTile = kFirstGrassTile+2,
  73.     kBlackTile,
  74.     kDiamondTile,
  75.     kDiamondTile2,
  76.     kLastDiamondTile,
  77.     kFirstExitTile,
  78.     kLastExitTile,
  79.     
  80.     kMaxNumTiles
  81. };
  82.  
  83.  
  84.  
  85. /***********/
  86. /* Globals */
  87. /***********/
  88.  
  89. SpriteWorldPtr        gSpriteWorldP;
  90. SpriteLayerPtr        gSpriteLayerP;
  91. TileMapStructPtr    gTileMapStructP;
  92. TileMapPtr            gTileMap;
  93. DrawProcPtr            gSpriteDrawProc = SWStdSpriteDrawProc;
  94. SpritePtr            gSimpleSpriteP, gDiamondMeterSpriteP;
  95. WindowPtr            gWindowP;
  96. Rect                gScreenMidRect;
  97. short                gCurrentLevel = 128;
  98. Boolean                gSpriteHitExit = false;
  99.  
  100. long                gNumDiamondsInMap = 0;    // Number of diamonds in the TileMap
  101. long                gNumDiamonds = 0;        // Number of diamonds sprite has collected
  102.  
  103. struct moveKeys        // Keeps track of which keys are up and which are down
  104. {
  105.     Boolean    up;
  106.     Boolean    right;
  107.     Boolean    down;
  108.     Boolean    left;
  109. } gKeys;
  110.  
  111.  
  112. ///--------------------------------------------------------------------------------------
  113. // Main
  114. ///--------------------------------------------------------------------------------------
  115.  
  116. void    main( void )
  117. {
  118.     Initialize(kNumberOfMoreMastersCalls);
  119.  
  120.     if (SWHasSystem7())
  121.     {
  122.         AllowKeyUpEvents();    // Part of SWGameUtils.c
  123.         SetCursor(*GetCursor(watchCursor));
  124.         
  125.         CreateSpriteWorld();
  126.         SetUpTiling();
  127.         CreateBallSprite();
  128.         CreateDiamondMeterSprite();
  129.         
  130.         SetCursor(&qd.arrow);
  131.         HideCursor();
  132.         
  133.         SetUpAnimation();
  134.         RunAnimation();
  135.         ShutDown();
  136.         
  137.         RestoreEventMask();    // Call this after AllowKeyUpEvents
  138.     }
  139.     else
  140.     {
  141.         CantRunOnThisMachine();
  142.     }
  143. }
  144.  
  145.  
  146. ///--------------------------------------------------------------------------------------
  147. // CreateSpriteWorld
  148. ///--------------------------------------------------------------------------------------
  149.  
  150. void    CreateSpriteWorld( void )
  151. {
  152.     Rect        offscreenRect, worldRect, windRect;
  153.     RgnHandle    mBarUpdateRgn;
  154.     OSErr        err;
  155.     
  156.     gWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  157.     
  158.     if (gWindowP != NULL)
  159.     {
  160.         if (kFullScreenWindow == true)
  161.         {
  162.             SizeWindow(gWindowP, qd.screenBits.bounds.right, 
  163.                     qd.screenBits.bounds.bottom, false);
  164.             MoveWindow(gWindowP, 0, 0, false);
  165.         }
  166.         else
  167.         {
  168.                 // Center window in screen
  169.             windRect = gWindowP->portRect;
  170.             CenterRect(&windRect, &qd.screenBits.bounds);
  171.             
  172.                 // Make sure window is aligned to long-word boundaries (for 8-bit mode)
  173.             windRect.left = windRect.left>>2<<2;
  174.             
  175.             MoveWindow(gWindowP, windRect.left, windRect.top, false);
  176.         }
  177.         
  178.         ShowWindow(gWindowP);
  179.         SetPort(gWindowP);
  180.         mBarUpdateRgn = SWHideMenuBar(gWindowP); // Must be done *after* showing window!
  181.         EraseRgn(mBarUpdateRgn);
  182.         
  183.         if (kInterlacedMode)
  184.             PaintRect(&gWindowP->portRect);    // Blacken window for Interlaced mode
  185.     }
  186.     else
  187.         CantFindResource();
  188.     
  189.     
  190.     err = SWEnterSpriteWorld();
  191.     FatalError(err);
  192.     
  193.     
  194.     worldRect = gWindowP->portRect;
  195.     InsetRect(&worldRect, kWorldRectInset, kWorldRectInset);
  196.     
  197.     
  198.         // Set size of offscreen area
  199.     offscreenRect = worldRect;
  200.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  201.     
  202.  
  203.         // Make offscreen area evenly divisible by tile width & height
  204.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  205.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  206.     
  207.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  208.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  209.     
  210.         // Create the scrolling sprite world
  211.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  212.             &worldRect, &offscreenRect, 0);
  213.     FatalError(err);
  214.     
  215.             // Create the sprite layer
  216.     err = SWCreateSpriteLayer(&gSpriteLayerP);
  217.     FatalError(err);
  218.     
  219.         // Add it to the world
  220.     SWAddSpriteLayer(gSpriteWorldP, gSpriteLayerP);
  221.         
  222.     
  223.         // Set the gSpriteDrawProc
  224.     if (gSpriteWorldP->pixelDepth == 8)        // If in 256 colors
  225.     {
  226.         if (kInterlacedMode)
  227.             gSpriteDrawProc = BP8BitInterlacedMaskDrawProc;
  228.         else
  229.             gSpriteDrawProc = BlitPixie8BitMaskDrawProc;
  230.     }
  231.     else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) )        // Not 256 colors
  232.     {
  233.             // Use interlaced drawProcs unless in B&W, where interlacing is ugly
  234.         if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
  235.             gSpriteDrawProc = BPAllBitInterlacedMaskDrawProc;
  236.         else
  237.             gSpriteDrawProc = BlitPixieAllBitMaskDrawProc;
  238.     }
  239. }
  240.  
  241.  
  242. ///--------------------------------------------------------------------------------------
  243. // SetUpTiling
  244. ///--------------------------------------------------------------------------------------
  245.  
  246. void    SetUpTiling( void )
  247. {    
  248.     OSErr        err;
  249.  
  250.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  251.     FatalError(err);
  252.     
  253.     err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
  254.     FatalError(err);
  255.     
  256.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  257.     gTileMap = gTileMapStructP->tileMap;
  258.  
  259.         // Load the tiles
  260.     err = SWLoadTilesFromPictResource(
  261.         gSpriteWorldP, 
  262.         kFirstWallTile,            // startTileID 
  263.         kLastExitTile,            // endTileID
  264.         kTilePictResID,            // pictResID
  265.         0,                        // maskResID
  266.         kNoMask,                // maskType
  267.         0,                        // horizBorderWidth
  268.         0);                        // vertBorderHeight
  269.     FatalError(err);
  270.     
  271.     CountDiamonds();
  272. }
  273.  
  274.  
  275. ///--------------------------------------------------------------------------------------
  276. // CountDiamonds - Counts the number of diamonds in the TileMap
  277. ///--------------------------------------------------------------------------------------
  278.  
  279. void    CountDiamonds( void )
  280. {
  281.     short    row, col;
  282.     
  283.     gNumDiamondsInMap = 0;
  284.     gNumDiamonds = 0;
  285.     
  286.     for (row = 0; row < gSpriteWorldP->tileLayerArray[0]->numRows; row++)
  287.     {
  288.         for (col = 0; col < gSpriteWorldP->tileLayerArray[0]->numCols; col++)
  289.         {
  290.             if (gTileMap[row][col] == kDiamondTile)
  291.                 gNumDiamondsInMap++;
  292.         }
  293.     }
  294. }
  295.  
  296.     
  297. ///--------------------------------------------------------------------------------------
  298. // CreateBallSprite
  299. ///--------------------------------------------------------------------------------------
  300.  
  301. void    CreateBallSprite( void )
  302. {
  303.     OSErr                err;
  304.     
  305.         // Create the ball sprite
  306.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gSimpleSpriteP, NULL, 
  307.             128, 1, kFatMask);    
  308.     FatalError(err);
  309.     
  310.         // Set up the ball sprite
  311.     SWAddSprite(gSpriteLayerP, gSimpleSpriteP);
  312.     SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
  313.     SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  314.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  315.     SWSetSpriteDrawProc(gSimpleSpriteP, gSpriteDrawProc);
  316. }
  317.  
  318.  
  319. ///--------------------------------------------------------------------------------------
  320. // CreateDiamondMeterSprite
  321. ///--------------------------------------------------------------------------------------
  322.  
  323. void    CreateDiamondMeterSprite( void )
  324. {
  325.     OSErr                err;
  326.     
  327.         // Create the diamond meter sprite
  328.     err = SWCreateSpriteFromPictResource(gSpriteWorldP, &gDiamondMeterSpriteP, NULL,
  329.                 kSpritePictResID, kSpritePictResID, 1, kPixelMask);
  330.     FatalError(err);
  331.     
  332.     SWAddSprite(gSpriteLayerP, gDiamondMeterSpriteP);
  333.     SWSetSpriteDrawProc(gDiamondMeterSpriteP, gSpriteDrawProc);
  334. }
  335.  
  336.  
  337. ///--------------------------------------------------------------------------------------
  338. // SetUpAnimation
  339. ///--------------------------------------------------------------------------------------
  340.  
  341. void    SetUpAnimation( void )
  342. {
  343.     Rect        moveBoundsRect;
  344.     
  345.     SWLockSpriteWorld(gSpriteWorldP);
  346.     
  347.         // Set up data used by the SmoothScrollingWorldMoveProc
  348.     gScreenMidRect = gSimpleSpriteP->curFrameP->frameRect;
  349.     CenterRect( &gScreenMidRect, &gSpriteWorldP->backRect );
  350.     
  351.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  352.     SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
  353.     SWSetCleanUpSpriteWorld(gSpriteWorldP);
  354.     
  355.         // movement boundary = size of tileMap
  356.     SetRect(&moveBoundsRect, 0, 0, 
  357.         gSpriteWorldP->tileLayerArray[0]->numCols * gSpriteWorldP->tileWidth, 
  358.         gSpriteWorldP->tileLayerArray[0]->numRows * gSpriteWorldP->tileHeight);
  359.     
  360.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  361.     SWSetScrollingWorldMoveProc(gSpriteWorldP, SmoothScrollingWorldMoveProc, gSimpleSpriteP);
  362.     
  363.     SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
  364.     
  365.         // Move visScrollRect to starting sprite position
  366.     SWMoveVisScrollRect(gSpriteWorldP, 
  367.         gSpriteWorldP->followSpriteP->destFrameRect.left - gSpriteWorldP->backRect.right/2,
  368.         gSpriteWorldP->followSpriteP->destFrameRect.top - gSpriteWorldP->backRect.bottom/2);
  369.     
  370.         // Set starting position of diamond meter sprite
  371.     DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  372.  
  373.     if (gSpriteWorldP->pixelDepth == 8)        // If in 256 colors
  374.     {
  375.         if (kInterlacedMode)
  376.         {
  377.             SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BP8BitInterlacedRectDrawProc);
  378.             SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BP8BitInterlacedRectDrawProc);
  379.             SWSetPartialMaskDrawProc(gSpriteWorldP, BP8BitInterlacedPartialMaskDrawProc);
  380.             SWSetDoubleRectDrawProc(gSpriteWorldP, BP8BitInterlacedDoubleRectDrawProc);
  381.         }
  382.         else
  383.         {
  384.             SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixie8BitRectDrawProc);
  385.             SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixie8BitPartialMaskDrawProc);
  386.             SWSetDoubleRectDrawProc(gSpriteWorldP, BlitPixie8BitDoubleRectDrawProc);
  387.             
  388. #if !SW_PPC        // CopyBits is faster for full-screen blitting in PPC
  389.             SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BlitPixie8BitRectDrawProc);
  390. #endif
  391.         }
  392.     }    // When running on PPC, we can't use the AllBit blitters in lower than 8-bit
  393.     else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) )    // Not 256 colors
  394.     {
  395.         if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
  396.         {
  397.                 // Use interlaced drawProcs unless in B&W, where interlacing is ugly
  398.             SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BPAllBitInterlacedRectDrawProc);
  399.             SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BPAllBitInterlacedRectDrawProc);
  400.             SWSetPartialMaskDrawProc(gSpriteWorldP, BPAllBitInterlacedPartialMaskDrawProc);
  401.             if (gSpriteWorldP->pixelDepth == 16)
  402.                 SWSetDoubleRectDrawProc(gSpriteWorldP, BP16BitInterlacedDoubleRectDrawProc);
  403.         }
  404.         else
  405.         {
  406.             SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, BlitPixieAllBitRectDrawProc);
  407.             SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, BlitPixieAllBitRectDrawProc);
  408.             SWSetPartialMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
  409.             if (gSpriteWorldP->pixelDepth == 16)
  410.                 SWSetDoubleRectDrawProc(gSpriteWorldP, BlitPixie16BitDoubleRectDrawProc);
  411.         }
  412.     }
  413.     
  414.     
  415.         // Make sure CopyBits, if used, doesn't try to colorize things
  416.     SWSetPortToWindow(gSpriteWorldP);
  417.     ForeColor(blackColor);
  418.     BackColor(whiteColor);
  419.     
  420.     SWDrawTilesInBackground(gSpriteWorldP);
  421.     SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
  422. }
  423.  
  424.  
  425. ///--------------------------------------------------------------------------------------
  426. //  RunAnimation
  427. ///--------------------------------------------------------------------------------------
  428.  
  429. void    RunAnimation( void )
  430. {
  431.     unsigned long        frames;
  432.     
  433.     frames = 0;
  434.     StartTimer();
  435.  
  436.     FatalError( SWStickyError() ); // Make sure no errors got past us during setup
  437.  
  438.     while (!Button())
  439.     {
  440.         SWProcessScrollingSpriteWorld(gSpriteWorldP);
  441.         
  442.             // We call this in case the Control Strip or something changes our window's visRgn
  443.         KeepMenuBarHidden(gWindowP);
  444.  
  445.             // Move diamond meter sprite to new visScrollRect location
  446.         DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  447.         
  448.         FatalError( SWStickyError() ); // Make sure no errors occurred during a MoveProc, etc.
  449.     
  450.         SWAnimateScrollingSpriteWorld(gSpriteWorldP);
  451.         
  452.         if (gSpriteWorldP->frameHasOccurred)
  453.         {
  454.             frames++;
  455.             
  456.             if (gSpriteHitExit)
  457.                 AdvanceLevel();
  458.         }
  459.     }
  460.     
  461.     
  462.     SWShowMenuBar(gWindowP);
  463.     ShowResults(frames);
  464. }
  465.  
  466.  
  467. ///--------------------------------------------------------------------------------------
  468. //  ShutDown (clean up and dispose of the SpriteWorld)
  469. ///--------------------------------------------------------------------------------------
  470.  
  471. void    ShutDown( void )
  472. {
  473.     SWDisposeSpriteWorld(&gSpriteWorldP);
  474.     SWExitSpriteWorld();
  475.     
  476.     FlushEvents(everyEvent, 0);
  477.     ShowCursor();
  478. }
  479.  
  480.  
  481. ///--------------------------------------------------------------------------------------
  482. //  TileChangeProc
  483. ///--------------------------------------------------------------------------------------
  484.  
  485. SW_FUNC void TileChangeProc(
  486.     SpriteWorldPtr spriteWorldP)
  487. {
  488.     short            curImage;
  489.     static short    diamondDelay = 0, exitDelay = 0;
  490.     static short    oldTicks = 0;
  491.     short            ticksPassed, ticks;
  492.     
  493.         // Initialize oldTicks the first time this function is called
  494.     if (oldTicks == 0)
  495.         oldTicks = TickCount();
  496.     
  497.     ticks = TickCount();
  498.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  499.     oldTicks = ticks;
  500.     
  501.     
  502.         // kDiamondTile
  503.     diamondDelay += ticksPassed;
  504.     if (diamondDelay >= kDiamondFrameRate)
  505.     {
  506.         curImage = spriteWorldP->curTileImage[kDiamondTile];
  507.         if (curImage < kLastDiamondTile)
  508.             curImage++;
  509.         else
  510.             curImage = kDiamondTile;
  511.         
  512.         SWChangeTileImage(spriteWorldP, kDiamondTile, curImage);
  513.         diamondDelay = 0;
  514.     }
  515.     
  516.     
  517.         // Flash exit tile if all diamonds have been collected
  518.     exitDelay += ticksPassed;
  519.     if (exitDelay >= kExitFrameRate)
  520.     {
  521.         if  (!kRequireDiamondsToExit || gNumDiamonds == gNumDiamondsInMap)
  522.         {
  523.             curImage = spriteWorldP->curTileImage[ kFirstExitTile ];
  524.             if ( curImage < kLastExitTile )
  525.                 curImage++;
  526.             else
  527.                 curImage = kFirstExitTile;
  528.             
  529.             SWChangeTileImage( spriteWorldP, kFirstExitTile, curImage );
  530.         }
  531.         exitDelay = 0;
  532.     }
  533. }
  534.  
  535.  
  536. ///--------------------------------------------------------------------------------------
  537. //  KeySpriteMoveProc
  538. ///--------------------------------------------------------------------------------------
  539.  
  540. SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
  541. {
  542.     short    row, col;
  543.     short    rowDelta, colDelta;
  544.     short    tile;
  545.     
  546.     UpdateKeys();    // Put the latest key values in the keys structure
  547.     
  548.     
  549.     row = srcSpriteP->destFrameRect.top / kTileHeight;
  550.     col = srcSpriteP->destFrameRect.left / kTileWidth;
  551.  
  552.     if (row * kTileHeight == srcSpriteP->destFrameRect.top &&
  553.         col * kTileWidth == srcSpriteP->destFrameRect.left)
  554.     {
  555.         tile = gTileMap[row][col];
  556.         
  557.             // Leave black trail behind sprite
  558.         if ( (tile >= kFirstGrassTile && tile <= kLastGrassTile) || tile == kDiamondTile)
  559.             SWDrawTile(gSpriteWorldP, 0, row, col, kBlackTile);
  560.             
  561.         if (tile == kDiamondTile)
  562.         {
  563.             gNumDiamonds++;            // Increase number of diamonds sprite has collected
  564.             UpdateDiamondMeter();    // Update meter
  565.         }
  566.         else if (tile == kFirstExitTile)
  567.         {
  568.             if  (!kRequireDiamondsToExit || gNumDiamonds == gNumDiamondsInMap)
  569.             {
  570.                 gSpriteHitExit = true;
  571.                 return;
  572.             }
  573.         }
  574.         
  575.  
  576.         rowDelta = 0;
  577.         colDelta = 0;
  578.         
  579.         if (gKeys.left)
  580.             colDelta = -1;
  581.         else if (gKeys.right)
  582.             colDelta = 1;
  583.         else if (gKeys.up)
  584.             rowDelta = -1;
  585.         else if (gKeys.down)
  586.             rowDelta = 1;
  587.         
  588.                 
  589.         
  590.         tile = gTileMap[row + rowDelta][col + colDelta];
  591.         
  592.         if (tile < kFirstWallTile || tile > kLastWallTile)
  593.         {
  594.             srcSpriteP->vertMoveDelta = rowDelta * kSpriteMoveDelta;
  595.             srcSpriteP->horizMoveDelta = colDelta * kSpriteMoveDelta;
  596.         }
  597.         else
  598.         {
  599.             srcSpriteP->vertMoveDelta = 0;
  600.             srcSpriteP->horizMoveDelta = 0;
  601.         }
  602.     }
  603.     
  604.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  605. }
  606.  
  607.  
  608. ///--------------------------------------------------------------------------------------
  609. //  DiamondMeterSpriteMoveProc - not installed as a MoveProc, but called directly
  610. ///--------------------------------------------------------------------------------------
  611.  
  612. SW_FUNC void DiamondMeterSpriteMoveProc(SpritePtr srcSpriteP)
  613. {
  614.         // Move sprite to top-left corner of current visScrollRect location
  615.     SWMoveSprite(srcSpriteP, 
  616.         gSpriteWorldP->visScrollRect.left + 10, 
  617.         gSpriteWorldP->visScrollRect.top + 10);
  618. }
  619.  
  620.  
  621. ///--------------------------------------------------------------------------------------
  622. //  UpdateDiamondMeter - change the meter Sprite's image and mask
  623. ///--------------------------------------------------------------------------------------
  624.  
  625. SW_FUNC void UpdateDiamondMeter( void )
  626. {
  627.     double    percent;
  628.     Rect    meterRect;
  629.     
  630.     percent = (double)gNumDiamonds / gNumDiamondsInMap;
  631.     
  632.         // 108 = length of meter; 17 = offset from start of meter
  633.     SetRect(&meterRect, 17, 2, (108 * percent) + 17, 14);
  634.     
  635.     
  636.         // Set port to our sprite's framePort GWorld
  637.     SetGWorld(gDiamondMeterSpriteP->curFrameP->framePort, nil);
  638.     
  639.     ForeColor(magentaColor);
  640.     PaintRect(&meterRect);
  641.     
  642.         // IMPORTANT: Set the color back when done! (In case CopyBits is used later)
  643.     ForeColor(blackColor);
  644.     
  645.     
  646.         // Set port to our sprite's pixel mask GWorld
  647.     SetGWorld(gDiamondMeterSpriteP->curFrameP->maskPort, nil);
  648.     
  649.         // Mask image is inverted when in 8-bit or less
  650.     if (gSpriteWorldP->pixelDepth <= 8)
  651.         ForeColor(whiteColor);
  652.     else
  653.         ForeColor(blackColor);
  654.     
  655.     PaintRect(&meterRect);
  656.     ForeColor(blackColor);
  657.     
  658.     
  659.         // Set sprite to be redrawn, since we've changed its image
  660.     gDiamondMeterSpriteP->needsToBeDrawn = true;
  661. }
  662.  
  663.  
  664. ///--------------------------------------------------------------------------------------
  665. //  SmoothScrollingWorldMoveProc - our scrolling WorldMoveProc
  666. ///--------------------------------------------------------------------------------------
  667.  
  668. SW_FUNC void SmoothScrollingWorldMoveProc(
  669.     SpriteWorldPtr spriteWorldP,
  670.     SpritePtr followSpriteP)
  671. {    
  672.     short    screenMidRectTop, screenMidRectLeft;
  673.     
  674.     screenMidRectTop = gScreenMidRect.top + spriteWorldP->visScrollRect.top;
  675.     screenMidRectLeft = gScreenMidRect.left + spriteWorldP->visScrollRect.left;
  676.     
  677.     
  678.     spriteWorldP->horizScrollDelta = (kSpriteMoveDelta * 
  679.         (followSpriteP->destFrameRect.left - screenMidRectLeft) ) / kSpriteMoveDistance;
  680.     
  681.     spriteWorldP->vertScrollDelta = (kSpriteMoveDelta * 
  682.         (followSpriteP->destFrameRect.top - screenMidRectTop) ) / kSpriteMoveDistance;
  683.     
  684.     if (kInterlacedMode)
  685.         spriteWorldP->vertScrollDelta = spriteWorldP->vertScrollDelta>>1<<1;
  686. }
  687.  
  688.  
  689. ///--------------------------------------------------------------------------------------
  690. //  UpdateKeys (Put the latest key values in the keys structure)
  691. ///--------------------------------------------------------------------------------------
  692.  
  693. void    UpdateKeys( void )
  694. {
  695.     EventRecord        event;
  696.     short            theKey;
  697.     Boolean            isDown;
  698.     
  699.     while ( GetOSEvent( (keyUpMask | keyDownMask), &event ) )
  700.     {
  701.         theKey = (event.message & keyCodeMask) >> 8;
  702.         isDown = (event.what != keyUp);
  703.         
  704.         if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
  705.             gKeys.left = isDown;
  706.         else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
  707.             gKeys.right = isDown;
  708.         else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
  709.             gKeys.down = isDown;
  710.         else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
  711.             gKeys.up = isDown;
  712.     }
  713. }
  714.  
  715.  
  716. ///--------------------------------------------------------------------------------------
  717. //  AdvanceLevel
  718. ///--------------------------------------------------------------------------------------
  719.  
  720. void    AdvanceLevel( void )
  721. {
  722.     Rect            moveBoundsRect;
  723.     unsigned long    junkTime;
  724.     OSErr            err;
  725.     
  726.     gCurrentLevel++;
  727.     gSpriteHitExit = false;
  728.     
  729.     SWDisposeTileMap(&gTileMapStructP);
  730.     err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
  731.     if (err)
  732.     {
  733.         gCurrentLevel = 128;
  734.         err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
  735.         FatalError(err);
  736.     }
  737.     
  738.     gTileMap = gTileMapStructP->tileMap;
  739.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  740.     
  741.         // Reset scrolling moveBounds for new TileMap
  742.     SetRect(&moveBoundsRect, 0, 0, 
  743.         gTileMapStructP->numCols * kTileWidth, 
  744.         gTileMapStructP->numRows * kTileHeight);
  745.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  746.     
  747.     Delay(15, &junkTime);
  748.     
  749.     CountDiamonds();
  750.     
  751.         // Update Diamond Meter Sprite, since we've changed its frame and mask
  752.     SWUpdateSpriteFromPictResource(gDiamondMeterSpriteP, kSpritePictResID);
  753.     SWUpdateFrameMasks(gSpriteWorldP, gDiamondMeterSpriteP->curFrameP);
  754.     
  755.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  756.     SWMoveSprite(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  757.     SWMoveVisScrollRect(gSpriteWorldP, 0, 0);
  758.     
  759.     SWResetCurrentTileImages(gSpriteWorldP);
  760.     SWDrawTilesInBackground(gSpriteWorldP);
  761.     SWUpdateSpriteWorld(gSpriteWorldP, false);
  762. }
  763.